using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Wolfpack.Core;
using Wolfpack.Core.Checks;
using Wolfpack.Core.Interfaces.Entities;
using Wolfpack.Core.Notification;

namespace Wolfpack.Contrib.BuildAnalytics.Tfs.Checks
{
    public class TfsBuildNotificationCheck : HealthCheckBase<TfsBuildNotificationCheckConfig>
    {
        private Dictionary<string, string> _lastBuildTracker;

        public TfsBuildNotificationCheck(TfsBuildNotificationCheckConfig config)
            : base(config)
        {
        }

        public override void Initialise()
        {
            _lastBuildTracker = new Dictionary<string, string>();
        }

        public override void Execute()
        {
            var tfs = new TfsTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(_config.ServerUrl));
            var buildServer = tfs.GetService<IBuildServer>();


            foreach (var buildDefinition in _config.BuildDefinitions)
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();

                var build = buildServer.QueryBuilds(_config.TeamProjectName, buildDefinition)
                           .Where(x => x.BuildFinished)
                           .OrderByDescending(x => x.FinishTime)
                           .Take(1)
                           .Where(x => !_lastBuildTracker.ContainsKey(buildDefinition) ||
                                    // tracking and changed from last
                                    (_lastBuildTracker.ContainsKey(buildDefinition) &&
                                    !_lastBuildTracker[buildDefinition].Equals(x.BuildNumber, StringComparison.OrdinalIgnoreCase)))
                           .Select(x => new { Key = buildDefinition, LastBuild = x })
                           .FirstOrDefault();

                stopwatch.Stop();
                Logger.Debug("TfsBuildNotificationCheck checked for new builds of {0}/{1} in {2}ms", _config.TeamProjectName, buildDefinition, stopwatch.ElapsedMilliseconds);

                if (build == null)
                    continue;

                Logger.Debug("TfsBuildNotificationCheck inspecting {0}/{1} on {2}", _config.TeamProjectName, build.Key, _config.ServerUrl);
                _lastBuildTracker[build.Key] = build.LastBuild.BuildNumber;

                var buildResult = (build.LastBuild.Status == BuildStatus.Succeeded);

                Logger.Debug("\tNew build '{0}/{1}' has been detected (Success:={2})",
                    _config.TeamProjectName,
                    build.Key,
                    buildResult);

                var duration = build.LastBuild.FinishTime.Subtract(build.LastBuild.StartTime);

                var identity = new PluginDescriptor
                {
                    Name = string.Format("{0}-{1}-{2}", Identity.Name, _config.TeamProjectName, build.Key),
                    TypeId = Identity.TypeId
                };

                var data = HealthCheckData.For(identity, "Build '{0}' of project '{1}/{2}: {3}",
                    build.LastBuild.BuildNumber, _config.TeamProjectName, build.Key, build.LastBuild.Status)
                    .ResultIs(buildResult)
                    .ResultCountIs(duration.TotalSeconds)
                    .SetDuration(duration)
                    .SetGeneratedOnUtc(build.LastBuild.FinishTime)
                    .AddTag(build.LastBuild.BuildNumber)
                    .AddProperty(NotificationProperties.ServerUrl, _config.ServerUrl)
                    .AddProperty(NotificationProperties.ProjectName, _config.TeamProjectName)
                    .AddProperty(NotificationProperties.BuildId, build.LastBuild.BuildNumber)
                    .AddProperty(NotificationProperties.BuildUri, build.LastBuild.Uri.OriginalString)
                    .AddProperty(NotificationProperties.ConfigurationName, build.Key);

                Publish(NotificationRequestBuilder.For(_config.NotificationMode, data).Build());
            }
        }

        protected override PluginDescriptor BuildIdentity()
        {
            return new PluginDescriptor
                       {
                           Description = "Detects new TFS builds and reports on their state",
                           TypeId = new Guid("60BD38A0-92BB-424F-9DC9-E98CE939D3FB"),
                           Name = _config.FriendlyId
                       };
        }
    }
}